from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from .models import SportTrack, SportTrackPoint, DeviceData, SportRecord, WeightRecord
import json
import math
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from .models import DietRecord, FoodNutrition
from .serializers import DietRecordSerializer
from django.db.models import Q
from datetime import date
from utils.authentication import CustomJWTAuthentication
from django.utils.decorators import method_decorator
from .serializers import WeightRecordSerializer, SportRecordSerializer
from rest_framework.decorators import api_view, permission_classes, authentication_classes

# Create your views here.

def haversine(lon1, lat1, lon2, lat2):
    """
    计算两点间距离（单位：米）
    """
    R = 6371000  # 地球半径，单位米
    from math import radians, sin, cos, sqrt, atan2
    dlon = radians(lon2 - lon1)
    dlat = radians(lat2 - lat1)
    a = sin(dlat/2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon/2)**2
    c = 2 * atan2(sqrt(a), sqrt(1-a))
    return R * c

@api_view(['POST'])
@authentication_classes([CustomJWTAuthentication])
@permission_classes([IsAuthenticated])
def create_track(request):
    """
    创建一条新的运动轨迹，返回track_id
    """
    user = request.user
    name = request.data.get('name', '运动轨迹')
    track = SportTrack.objects.create(user=user, name=name)
    return Response({'track_id': track.id})

@csrf_exempt
def upload_track_point(request):
    """
    上传一个轨迹点
    """
    if request.method == 'POST':
        data = json.loads(request.body)
        track_id = data['track_id']
        lat = data['lat']
        lng = data['lng']
        timestamp = data.get('timestamp', None)
        track = SportTrack.objects.get(id=track_id)
        point = SportTrackPoint.objects.create(
            track=track,
            lat=lat,
            lng=lng,
            timestamp=timestamp or timezone.now()
        )
        return JsonResponse({'status': 'ok', 'point_id': point.id})

def get_track_points(request, track_id):
    """
    获取某条轨迹的所有点
    """
    points = SportTrackPoint.objects.filter(track_id=track_id).order_by('timestamp')
    data = [{'lat': p.lat, 'lng': p.lng, 'timestamp': p.timestamp} for p in points]
    return JsonResponse({'points': data})

@csrf_exempt
def end_track(request):
    """
    结束运动，统计总距离和用时，并保存到运动统计表
    """
    if request.method == 'POST':
        data = json.loads(request.body)
        track_id = data['track_id']
        track = SportTrack.objects.get(id=track_id)
        track.end_time = timezone.now()

        # 统计总距离
        points = SportTrackPoint.objects.filter(track=track).order_by('timestamp')
        total_distance = 0
        prev = None
        for p in points:
            if prev:
                total_distance += haversine(prev.lng, prev.lat, p.lng, p.lat)
            prev = p
        track.total_distance = total_distance
        track.save()

        # 统计用时
        if points.exists():
            start_time = points.first().timestamp
            end_time = points.last().timestamp
            duration = (end_time - start_time).total_seconds()  # 单位：秒
        else:
            duration = 0

        # 估算消耗卡路里（体重优先取用户最新体重）
        user_weight = 70
        if track.user and hasattr(track.user, 'weightrecord_set'):
            latest_weight = track.user.weightrecord_set.order_by('-date').first()
            if latest_weight:
                user_weight = latest_weight.weight
        calories = user_weight * (total_distance / 1000) * 1.036

        # 保存到运动统计表
        SportRecord.objects.create(
            user=track.user,
            date=date.today(),
            type='实时运动',
            duration=int(duration // 60),  # 分钟
            distance=round(total_distance / 1000, 2),  # 公里
            calories=round(calories, 2),
            note='自动生成'
        )

        return JsonResponse({
            'status': 'ok',
            'total_distance': round(total_distance, 2),  # 单位：米
            'duration': int(duration)  # 单位：秒
        })

@csrf_exempt
def upload_device_data(request):
    """
    上传设备实时数据（如心率、步频等）
    前端可定时上传当前心率、步频等数据，后端存入 DeviceData 表。
    支持与用户、运动轨迹关联。
    """
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            user = request.user if request.user.is_authenticated else None  # 当前用户
            track_id = data.get('track_id')  # 运动轨迹ID
            heart_rate = data.get('heart_rate')  # 心率
            step = data.get('step')  # 步频/步数
            track = SportTrack.objects.get(id=track_id) if track_id else None  # 关联轨迹
            # 存储设备数据
            DeviceData.objects.create(
                user=user,
                track=track,
                heart_rate=heart_rate,
                step=step
            )
            return JsonResponse({'status': 'ok'})
        except Exception as e:
            return JsonResponse({'status': 'error', 'msg': str(e)}, status=400)
    return JsonResponse({'status': 'error', 'msg': 'Invalid method'}, status=405)

class SportRecordView(APIView):
    authentication_classes = [CustomJWTAuthentication]
    permission_classes = [IsAuthenticated]

    @method_decorator(csrf_exempt)
    def post(self, request):
        """手动添加运动记录"""
        from .models import SportRecord
        print('request.user:', request.user, type(request.user))
        print('SportRecord.user.related_model:', SportRecord._meta.get_field('user').related_model)
        serializer = SportRecordSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(user=request.user)
            return Response(serializer.data)
        return Response(serializer.errors, status=400)

    def get(self, request):
        """获取当前用户的所有运动记录，按日期倒序"""
        records = SportRecord.objects.filter(user_id=request.user.pk).order_by('-date', '-created_at')
        serializer = SportRecordSerializer(records, many=True)
        return Response(serializer.data)

class WeightRecordView(APIView):
    authentication_classes = [CustomJWTAuthentication]
    permission_classes = [IsAuthenticated]

    @method_decorator(csrf_exempt)
    def post(self, request):
        """手动添加体重记录"""
        serializer = WeightRecordSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(user=request.user)
            return Response(serializer.data)
        return Response(serializer.errors, status=400)

    def get(self, request):
        """获取当前用户的所有体重记录，按日期倒序"""
        records = WeightRecord.objects.filter(user_id=request.user.pk).order_by('-date', '-created_at')
        serializer = WeightRecordSerializer(records, many=True)
        return Response(serializer.data)

class DietRecordView(APIView):
    authentication_classes = [CustomJWTAuthentication]
    permission_classes = [IsAuthenticated]

    @method_decorator(csrf_exempt)
    def post(self, request):
        """手动添加饮食记录，自动查表计算热量（支持模糊匹配）"""
        data = request.data.copy()
        food = data.get('food')
        weight = float(data.get('weight', 0))
        calorie = None
        if food and weight > 0:
            # 优先精确查找
            food_obj = FoodNutrition.objects.filter(name=food).first()
            if not food_obj:
                # 支持模糊查找
                food_obj = FoodNutrition.objects.filter(name__icontains=food).first()
            if food_obj:
                calorie = round(float(food_obj.energy) * weight / 100, 2)
        serializer = DietRecordSerializer(data=data)
        if serializer.is_valid():
            serializer.save(user=request.user)
            resp = serializer.data
            resp['calorie'] = calorie
            return Response(resp)
        return Response(serializer.errors, status=400)

    def get(self, request):
        """获取当天分三餐饮食记录，并动态补充热量，返回总热量total_calorie"""
        date = request.query_params.get('date')
        if not date:
            from datetime import date as dtdate
            date = dtdate.today().isoformat()
        records = DietRecord.objects.filter(user=request.user, date=date)
        data = {'breakfast': [], 'lunch': [], 'dinner': []}
        total_calorie = 0
        for r in records:
            item = DietRecordSerializer(r).data
            calorie = None
            if r.food and r.weight:
                food_obj = FoodNutrition.objects.filter(name=r.food).first()
                if not food_obj:
                    food_obj = FoodNutrition.objects.filter(name__icontains=r.food).first()
                if food_obj:
                    calorie = round(float(food_obj.energy) * float(r.weight) / 100, 2)
            item['calorie'] = calorie if calorie is not None else 0
            total_calorie += item['calorie']
            data[r.meal_type].append(item)
        data['total_calorie'] = total_calorie
        return Response(data)
